//1.new一个对象的实现
function _new(){
    let _target={};
    const [func,...args]=[...arguments];
    _target.__proto__=func.prototype;
    let result=func.call(_target,...args);
    if(result&&(typeof(result)==="object"||typeof(result)=="function")){
        return result;
    }
    return _target;
}

function A(name,age){
    this.name=name;
    this.age=age;
}

var obj=_new(A,"张三",18);
console.log("创建的对象",obj);



//2.函数的柯里化核心代码
function Currying(){
  const [fn,...args]=[...arguments];
  if(fn.length<=args.length){
      return fn(...args);
  }else{
      return function(...args2){
          return Currying(fn,...args,...args2);
      }
  }
}

function sum(a,b,c){
    return a+b+c;
}

console.log(Currying(sum,1)(2)(3));
console.log(Currying(sum)(1,2)(3));
console.log(Currying(sum)(1,2,3));


//3.深拷贝的实现
function deepClone(obj){
    let objClone=Array.isArray(obj)?[]:{};
    if(obj&&typeof(obj)==="object"){
        for (const key in obj) {
            if(obj.hasOwnProperty(key)){
                if(obj[key]&&typeof(obj[key])==="object"){
                   objClone[key]=deepClone(obj[key]);
                }else{
                    objClone[key] = obj[key]; 
                }
            }
        }
    }
    return objClone;
}

let obj1={
    a:{aa:'dsdf',bb:"dsdgg"},
    b:"aaaa",
    c:"dasds"
}

const cloneObj=deepClone(obj1)
console.log("新对象：",cloneObj);



//call和apply的实现
// 在 call 方法中获取调用call()函数
// 如果第一个参数没有传入，那么默认指向 window / global(非严格模式)
// 传入 call 的第一个参数是 this 指向的对象，根据隐式绑定的规则，我们知道 obj.foo(), foo() 中的 this 指向 obj;因此我们可以这样调用函数 thisArgs.func(...args)
// 返回执行结果
Function.prototype.call=function(){
    const [thisObj,...args]=[...arguments];
    if(!thisObj){
        thisObj=typeof thisObj==='undefined'&&window;
    }
    //this的指向是当前函数
    thisObj.func=this;
    let result=thisObj.func(...args);
    delete thisObj.func;
    return result;
}

Function.prototype.apply=function(thisObj,args){
    if(!thisObj){
        thisObj=typeof thisObj==='undefined'&&window;
    }
    thisObj.func=this;
    let result;
    if(!args){
        result=thisObj.func();
    }else{
        result=thisObj.func(...args);
    }
    delete thisObj.func;
    return result;
}

//防抖(实质利用闭包返回一个函数，是定时的timer一直都存在，通过判断timer来执行代码)
function debounce(fn,wait){
    let timer,results;
    const later=(context,args)=>setTimeout(()=>{
        timer=null;
        results=fn.apply(context,args);
        context=args=null;
    },wait)
    let debounce=function(...params){
        if(!timer){
            timer=later(this,params)
        }else{
            clearTimeout(timer)
            timer=later(this,params)
        }
    }
    debounce.cancel=function(){
        clearTimeout(timer);
        timer=null;
    }
    return debounce;
}

//节流
function throttle(fn,wait){
    let _lastTime=null;
    let throttled=function(...params){
        let _nowTime=new Date();
        if(_nowTime-_lastTime>=wait||_lastTime===null){
            fn(params);
            _lastTime=_nowTime;
        }
    }
    throttled.cancel=function(){
        _lastTime=null;
    }
    return throttled;
}
